home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / uemlsrc.arc / search.c < prev    next >
C/C++ Source or Header  |  1987-08-24  |  26KB  |  764 lines

  1. /*
  2.  * The functions in this file
  3.  * implement commands that search in the
  4.  * forward and backward directions. There are
  5.  * no special characters in the search strings.
  6.  * Probably should have a regular expression
  7.  * search, or something like that.
  8.  */
  9. #include        <stdio.h>
  10. #include        <ctype.h>
  11. #include        "ed.h"
  12.  
  13.  
  14. #define CCHR(x)  ((x)-'@')
  15.  
  16. #define SRCH_BEGIN      (0)                  /* Search sub-codes.    */
  17. #define SRCH_FORW       (-1)
  18. #define SRCH_BACK       (-2)
  19. #define SRCH_PREV       (-3)
  20. #define SRCH_NEXT       (-4)
  21. #define SRCH_NOPR       (-5)
  22. #define SRCH_ACCM       (-6)
  23. #define NSRCH   128                     /* Undoable search commands.    */
  24.  
  25. typedef struct  {
  26.         int     s_code;
  27.         LINE    *s_dotp;
  28.         int     s_doto;
  29. }       SRCHCOM;
  30.  
  31. static  SRCHCOM cmds[NSRCH];
  32. static  int     cip;
  33.  
  34. int     srch_lastdir = SRCH_NOPR;              /* Last search flags.   */
  35.  
  36. /*
  37.  * Search forward.
  38.  * Get a search string from the user, and search for it,
  39.  * starting at ".". If found, "." gets moved to just after the
  40.  * matched characters, and display does all the hard stuff.
  41.  * If not found, it just prints a message.
  42.  */
  43. forwsearch(f, n)
  44. register int f, n;
  45. {
  46.  
  47.         if ((f=readpattern("Search", &pat)) != TRUE)
  48.                 return (f);
  49.         if (forwsrch() == FALSE) {
  50.                 mlwrite("Not found");
  51.                 return (FALSE);
  52.         }
  53.         return (TRUE);
  54. }
  55.  
  56. /*
  57.  * Reverse search.
  58.  * Get a search string from the  user, and search, starting at "."
  59.  * and proceeding toward the front of the buffer. If found "." is left
  60.  * pointing at the first character of the pattern [the last character that
  61.  * was matched].
  62.  */
  63. backsearch(f, n)
  64. register int f, n;
  65. {
  66.  
  67.         if ((f=readpattern("Reverse search", &pat)) != TRUE)
  68.                 return (f);
  69.         if (backsrch() == FALSE) {
  70.                 mlwrite("Not found");
  71.                 return (FALSE);
  72.         }
  73.         return (TRUE);
  74. }
  75.  
  76.  
  77. /*
  78.  * This routine does the real work of a
  79.  * forward search. The pattern is sitting in the external
  80.  * variable "pat". If found, dot is updated, the window system
  81.  * is notified of the change, and TRUE is returned. If the
  82.  * string isn't found, FALSE is returned.
  83.  */
  84. forwsrch()
  85. {
  86.         register LINE   *clp;
  87.         register int    cbo;
  88.         register LINE   *tlp;
  89.         register int    tbo;
  90.         register char   *pp;
  91.         register int    c;
  92.  
  93.         clp = curwp->w_dotp;
  94.         cbo = curwp->w_doto;
  95.         while (clp != curbp->b_linep) {
  96.                 if (cbo == llength(clp)) {
  97.                         clp = lforw(clp);
  98.                         cbo = 0;
  99.                         c = '\n';
  100.                 } else
  101.                         c = lgetc(clp, cbo++);
  102.                 if (eq(c, pat[0]) != FALSE) {
  103.                         tlp = clp;
  104.                         tbo = cbo;
  105.                         pp  = &pat[1];
  106.                         while (*pp != 0) {
  107.                                 if (tlp == curbp->b_linep)
  108.                                         goto fail;
  109.                                 if (tbo == llength(tlp)) {
  110.                                         tlp = lforw(tlp);
  111.                                         if (tlp == curbp->b_linep)
  112.                                                 goto fail;
  113.                                         tbo = 0;
  114.                                         c = '\n';
  115.                                 } else
  116.                                         c = lgetc(tlp, tbo++);
  117.                                 if (eq(c, *pp++) == FALSE)
  118.                                         goto fail;
  119.                         }
  120.                         curwp->w_dotp  = tlp;
  121.                         curwp->w_doto  = tbo;
  122.                         curwp->w_flag |= WFMOVE;
  123.                         return (TRUE);
  124.                 }
  125.         fail:   ;
  126.         }
  127.         return (FALSE);
  128. }
  129.  
  130. /*
  131.  * This routine does the real work of a
  132.  * backward search. The pattern is sitting in the external
  133.  * variable "pat". If found, dot is updated, the window system
  134.  * is notified of the change, and TRUE is returned. If the
  135.  * string isn't found, FALSE is returned.
  136.  */
  137. backsrch()
  138. {
  139.         register LINE   *clp;
  140.         register int    cbo;
  141.         register LINE   *tlp;
  142.         register int    tbo;
  143.         register int    c;
  144.         register char   *epp;
  145.         register char   *pp;
  146.  
  147.         for (epp = &pat[0]; epp[1] != 0; ++epp)
  148.                 ;
  149.         clp = curwp->w_dotp;
  150.         cbo = curwp->w_doto;
  151.         for (;;) {
  152.                 if (cbo == 0) {
  153.                         clp = lback(clp);
  154.                         if (clp == curbp->b_linep)
  155.                                 return (FALSE);
  156.                         cbo = llength(clp)+1;
  157.                 }
  158.                 if (--cbo == llength(clp))
  159.                         c = '\n';
  160.                 else
  161.                         c = lgetc(clp,cbo);
  162.                 if (eq(c, *epp) != FALSE) {
  163.                         tlp = clp;
  164.                         tbo = cbo;
  165.                         pp  = epp;
  166.                         while (pp != &pat[0]) {
  167.                                 if (tbo == 0) {
  168.                                         tlp = lback(tlp);
  169.                                         if (tlp == curbp->b_linep)
  170.                                                 goto fail;
  171.                                         tbo = llength(tlp)+1;
  172.                                 }
  173.                                 if (--tbo == llength(tlp))
  174.                                         c = '\n';
  175.                                 else
  176.                                         c = lgetc(tlp,tbo);
  177.                                 if (eq(c, *--pp) == FALSE)
  178.                                         goto fail;
  179.                         }
  180.                         curwp->w_dotp  = tlp;
  181.                         curwp->w_doto  = tbo;
  182.                         curwp->w_flag |= WFMOVE;
  183.                         return (TRUE);
  184.                 }
  185.         fail:   ;
  186.         }
  187. }
  188.  
  189. /*
  190.  * Compare two characters.
  191.  * The "bc" comes from the buffer.
  192.  * It has it's case folded out. The
  193.  * "pc" is from the pattern.
  194.  */
  195. eq(bc, pc)
  196. register int    bc;
  197. register int    pc;
  198. {
  199.         if (bc>='a' && bc<='z')
  200.                 bc -= 0x20;
  201.         if (pc>='a' && pc<='z')
  202.                 pc -= 0x20;
  203.         if (bc == pc)
  204.                 return (TRUE);
  205.         return (FALSE);
  206. }
  207.  
  208. /*
  209.  * Read a pattern.
  210.  * Stash it in an external
  211.  * variable. The calling function
  212.  * passes the address of inpat. The "pat" is
  213.  * not updated if the user types in
  214.  * an empty line. If the user typed
  215.  * an empty line, and there is no
  216.  * old pattern, it is an error.
  217.  * Display the old pattern, in the
  218.  * style of Jeff Lomicka. There is
  219.  * some do-it-yourself control
  220.  * expansion.
  221.  */
  222. readpattern(prompt, inpat)
  223. char    *prompt;
  224. char    *inpat;
  225. {
  226.         register char   *cp1;
  227.         register char   *cp2;
  228.         register int    c;
  229.         register int    s;
  230.         char            tpat[NPAT+20];
  231.  
  232.         cp1 = &tpat[0];                         /* Copy prompt          */
  233.         cp2 = prompt;
  234.         while ((c = *cp2++) != '\0')
  235.                 *cp1++ = c;
  236.         if (inpat[0] != '\0') {                 /* Old pattern          */
  237.                 *cp1++ = ' ';
  238.                 *cp1++ = '[';
  239.                 cp2 = &inpat[0];
  240.                 while ((c = *cp2++) != 0) {
  241.                         if (cp1 < &tpat[NPAT+20-6]) {   /* "??]: \0"    */
  242.                                 if (c<0x20 || c==0x7F) {
  243.                                         *cp1++ = '^';
  244.                                         c ^= 0x40;
  245.                                 } else if (c == '%')    /* Map "%" to   */
  246.                                         *cp1++ = c;     /* "%%".        */
  247.                                 *cp1++ = c;
  248.                         }
  249.                 }
  250.                 *cp1++ = ']';
  251.         }
  252.         *cp1++ = ':';                           /* Finish prompt        */
  253.         *cp1++ = ' ';
  254.         *cp1++ = '\0';
  255.         s = mlreply(tpat, tpat, NPAT);          /* Read pattern         */
  256.         if (s == TRUE)                          /* Specified            */
  257.                 strcpy(inpat, tpat);
  258.         else if